<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<canvas id="canvas" width="800" height="600">
		Canvas not supported.
	</canvas>
</body>
<script type="text/javascript" src="../Charpter-05/requestNextAnimationFrame.js"></script>
<script type="text/javascript" src="Collision.js"></script>
<script type="text/javascript">
	var canvas = document.getElementById('canvas'),
		context = canvas.getContext('2d'),

		shapes = [],
		polygonPoints = [
			[new Point(250, 150), new Point(250, 200), new Point(300, 200)],
			[new Point(100, 100), new Point(100, 125), new Point(125, 125), new Point(125, 100)],
			[new Point(400, 100), new Point(380, 150), new Point(500, 150), new Point(520, 100)]
		],
		
		polygonStrokeStyles = ['blue', 'yellow', 'red'],
		polygonFillStyles = [
			'rgba(255, 255, 0, 0.7)',
			'rgba(100, 140, 230, 0.6)',
			'rgba(255, 255, 255, 0.8)'
		],

		shapeMoving = undefined,

		c1 = new Circle(150, 275, 20),
		c2 = new Circle(350, 350, 30),
		
		lastTime = undefined,
		velocity = {
			x: 350,
			y: 190
		},
		lastVelocity = {
			x: 350,
			y: 190
		},

		STICK_DELAY = 500,
		stuck = false,
		showInstructions = true; // 是否显示指令提示文字

// Functions.................................................................................................................................

	function windowToCanvas(x, y){
		var bbox = canvas.getBoundingClientRect();

		return {
			x: x - bbox.left * (canvas.width / bbox.width),
			y: y - bbox.top * (canvas.height / bbox.height)
		};
	}

	function drawShapes(){
		shapes.forEach(function(shape){
			shape.stroke(context);
			shape.fill(context);
		});
	}

	function collisionDetected(mtv){
		return mtv.axis != undefined || mtv.overlap !== 0;
	}

	function detectCollisions(){
		var textY = 30,
			bbox,
			mtv;

		if(shapeMoving){
			handleShapeCollisions();
			handleEdgeCollisions();
		}
	}

	function handleShapeCollisions(){
		var mtv;

		shapes.forEach(function(shape){
			if(shape !== shapeMoving){
				mtv = shapeMoving.collidesWithNew(shape);

				if(collisionDetected(mtv)){
					bounce(mtv, shapeMoving, shape);
				}
			}
		});
	}

	function separate(mtv){
		var dx,
			dy,
			velocityMagnitude,
			point;

		if(mtv.axis === undefined){
			point = new Point();
			velocityMagnitude = Math.sqrt(Math.pow(velocity.x, 2) + Math.pow(velocity.y, 2));

			point.x = velocity.x / velocityMagnitude;
			point.y = velocity.y / velocityMagnitude;

			mtv.axis = new Vector(point.x, point.y);
		}

		dx = mtv.axis.x * mtv.overlap;
		dy = mtv.axis.y * mtv.overlap;

		if((dx < 0 && velocity.x < 0) || (dx > 0 && velocity.x > 0)) dx = - dx;
		if((dy < 0 && velocity.y < 0) || (dy > 0 && velocity.y > 0)) dy = - dy;

		shapeMoving.move(dx, dy);
	}

	function checkMTVAxisDirection(mtv, collider, collidee){
		var centroid1,
			centroid2,
			centroidVector,
			centroidUnitVector;

		if(mtv.axis === undefined) return;

		centroid1 = new Vector(collider.centroid());
		centroid2 = new Vector(collidee.centroid());
		centroidVector = centroid2.subtract(centroid1);
		centroidUnitVector = (new Vector(centroidVector)).normalize();

		if(centroidUnitVector.dotProduct(mtv.axis) > 0){
			mtv.axis.x = - mtv.axis.x;
			mtv.axis.y = - mtv.axis.y;
		}
	}

	function bounce(mtv, collider, collidee){
		var dotProductRatio,
			vdotl,
			ldotl,
			point,
			veloctityVector = new Vector(new Point(velocity.x, velocity.y)),
			velocityUnitVector = veloctityVector.normalize(),
			velocityVectorMagnitude = veloctityVector.getMagnitude(),
			perpendicular; // 中垂线？

		if(shapeMoving){
			checkMTVAxisDirection(mtv, collider, collidee);

			point = new Point();

			if(mtv.axis !== undefined){
				perpendicular = mtv.axis.perpendicular();
			}else{
				perpendicular = new Vector(new Point(-velocityUnitVector.y, velocityUnitVector.x));
			}

			vdotl = velocityUnitVector.dotProduct(perpendicular);
			ldotl = perpendicular.dotProduct(perpendicular);
			dotProductRatio = vdotl / ldotl;

			point.x = 2 * dotProductRatio * perpendicular.x - velocityUnitVector.x;
			point.y = 2 * dotProductRatio * perpendicular.y - velocityUnitVector.y;

			separate(mtv);

			velocity.x = point.x * velocityVectorMagnitude;
			velocity.y = point.y * velocityVectorMagnitude;
		}
	}

// Event handlers..................................................................................................................................

	canvas.onmousedown = function(e){
		var location = windowToCanvas(e.clientX, e.clientY);

		if(showInstructions) showInstructions = false;

		velocity.x = lastVelocity.x;
		velocity.y = lastVelocity.y;

		shapeMoving = undefined;
		stuck = false;

		shapes.forEach(function(shape){
			if(shape.isPointInPath(context, location.x, location.y)){
				shapeMoving = shape;
			}
		});
	};

// Animation..........................................................................................................................................

	function animate(time){
		var elapsedTime,
		 	deltaX;

		if(lastTime === 0){
		 	if(time !== undefined){
		 		lastTime = time;
		 	}

		 	window.requestNextAnimationFrame(animate);
		 	return;
		}

		context.clearRect(0, 0, canvas.width, canvas.height);

		if(shapeMoving !== undefined){
		 	elapsedTime = parseFloat(time - lastTime) / 1000;
		 	shapeMoving.move(velocity.x * elapsedTime, velocity.y * elapsedTime);
		}

		detectCollisions();
		drawShapes();
		lastTime = time;

		if(showInstructions){
		 	context.fillStyle = 'cornflowerblue';
		 	context.font = '24px Arial';
		 	context.fillText('Click on a shape to animate it', 20, 40);
		}

		window.requestNextAnimationFrame(animate);
	}

// Initialization........................................................................................................................................

	for(var i = 0; i < polygonPoints.length; i++){
		var polygon = new Polygon(),
			points = polygonPoints[i];

		polygon.strokeStyle = polygonStrokeStyles[i];
		polygon.fillStyle = polygonFillStyles[i];

		points.forEach(function(point){
			polygon.addPoint(point.x, point.y);
		});

		shapes.push(polygon);
	} 

	c1.fillStyle = 'rgba(200, 50, 50, 0.5)';
	c2.fillStyle = 'rgba(200, 50, 150, 0.5)';

	shapes.push(c1);
	shapes.push(c2);

	context.shadowColor = 'rgba(100, 140, 255, 0.5)';
	context.shadowOffsetX = 2;
	context.shadowOffsetY = 2;
	context.shadowBlur = 4;
	context.font = '38px Arial';

	window.requestNextAnimationFrame(animate);
</script>
</html>